package com.trt.wiki;//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.util.Base64;
//import com.google.gson.Gson;
//import sun.misc.BASE64Decoder;
//
//import javax.imageio.ImageIO;
//import javax.swing.*;
//import java.awt.event.WindowAdapter;
//import java.awt.event.WindowEvent;
//import java.awt.image.BufferedImage;
//import java.io.*;
//import java.net.*;
//import java.util.Arrays;
//import java.util.HashMap;
//import java.util.Iterator;
//import java.util.Map;
//import java.util.zip.ZipInputStream;
//
//public class  Main   extends JFrame {
//
//    private static final long serialVersionUID = -580341982722536152L;
//    // label用于放置image
//    private JLabel label;
//
//    public static void main(String[] args) {
//        Main bsClient = new Main();
//    }
//
//    public Main() {
//
//        init();
//
//        getData();
//    }
//
//    // 初始化面板设置，设置一个label，放置image
//    public void init() {
//        this.setTitle("屏幕广播");
//        this.setBounds(270, 80, 200, 200);
//        try {
////            BufferedImage image = ImageIO.read(new File("E://Test//demo.jpg"));//首页 可以放LOGO
////            ImageIcon icon = new ImageIcon(image);
//            label = new JLabel();
//            label.setBounds(25, 25, 2048, 1536);
//        } catch(Exception e) {
//            e.printStackTrace();
//        }
//        this.add(label);
//
//        // 监听窗口关闭事件，关闭窗口的同时停止程序
//        this.addWindowListener(new WindowAdapter(){
//            @Override
//            public void windowClosing(WindowEvent e) {
//                System.out.println("关闭窗口");
//                System.exit(-1);
//            }
//        });
//
//        // 设置面板可见
//        this.setVisible(true);
//    }
//
//    // 启动一个线程监听端口，接收数据，解析成image并放入面板中显示
//    public void getData() {
//        Thread t = new Thread() {
//            private DatagramSocket receiver;
//            MulticastSocket multicastSocket = null;
//            DatagramSocket dsock =null;
//            @Override
//            public void run() {
//                try {
////                    InetAddress group = InetAddress.getByName("224.5.6.7");
//                    DatagramSocket dsock = new DatagramSocket(12345);
////                    multicastSocket.joinGroup(group);
//                    byte[] buffer = new byte[64*1024];
//                    DatagramPacket pack = new DatagramPacket(buffer, buffer.length);
//                    System.out.println("等待接收数据");
//                    // 用Map来存放image的各个包数据，Long是接收到数据包的时间戳，Integer是包的编号，
//                    // PackInfo中存放了解析出来的包数据、包数量、包编号、时间戳
//                    Map<Long, HashMap<Integer, PackInfo>> map = null;
//                    HashMap<Integer, PackInfo> map1 = null;
//                    // key用于存放接收的上一个包数据的时间戳
//                    long key = 0;
//                    while(true) {
//                        Long startTimeMillis = System.currentTimeMillis();
//                        System.out.println("(接收) 开始");
//                        dsock.receive(pack);
//                        System.out.println("收到一个数据报包 " + pack.getLength());
//
////                        String str= new String (pack.getData());
//                         String resultStr = new String(pack.getData(), 0, pack.getData().length);
//                         System.out.println("resultStr " + resultStr);
////                        TestEntity te = JSON.parseObject(resultStr, TestEntity.class);
//
//                        String [] a = resultStr.split(",");
//
//                        PackInfo packinfo =new PackInfo();
//                        packinfo.setCount(Integer.parseInt(a[3]));
//                        packinfo.setTime(Long.parseLong(a[1]));
//                        packinfo.setNum(Integer.parseInt(a[2]));
//                        packinfo.setData(a[0]);
//
//                        if(packinfo.getTime() > key) {
////                            map1 =new HashMap<Integer,PackInfo>();
////                            map1.put(packinfo.getNum(), packinfo);
//                            map = new HashMap<Long, HashMap<Integer,PackInfo>>();
//                            HashMap<Integer,PackInfo> value = new HashMap<Integer,PackInfo>();
//                            value.put(packinfo.getNum(), packinfo);
//                            map.put(packinfo.getTime(), value);
//                            // 更新key的值
//                            key = packinfo.getTime();
//                        }else if(packinfo.getTime() == key) {  // 如果时间戳相等则将包数据放入map中
////                            map.get(key).put(packinfo.getNum(), packinfo);
//                            checkMap(map);
//                            Long endTimeMillis = System.currentTimeMillis() - startTimeMillis;
//                            System.out.println("(接收) 结束，用时:"+ endTimeMillis+" ms");
//                        }
//
//                    }
//                } catch(Exception e) {
//                    e.printStackTrace();
//                }
//            }
//        };
//        // 作为守护线程，并启动
//        t.setDaemon(true);
//        t.start();
//    }
//
//    // 解析一个包的数据，并放入对象中返回
//    private PackInfo parsePackInfo(DatagramPacket pack) {
//        // 新建一个包数据对象存放数据
//        PackInfo packinfo = new PackInfo();
//
//        byte[] buffer = pack.getData();
//
//        // 取出时间戳，0-7的字节
//        long time = Utils.byte2Long(buffer, 0);
//        packinfo.setTime(time);
//
//        // 取出分割数量，8-11的字节
//        int count = Utils.byte2Int(buffer, 8);
//        packinfo.setCount(count);
//
//        // 取出当前编号，12-15的字节
//        int num = Utils.byte2Int(buffer, 12);
//        packinfo.setNum(num);
//
//        // 当前被压缩后的数据
//        byte[] data = new byte[pack.getLength()-16];
//        System.arraycopy(buffer, 16, data, 0, data.length);
////        packinfo.setData(data);
//
//        System.out.println(time + ", " + count + ", " + num + ", " + data.length);
//
//        return packinfo;
//    }
//
//    public static byte[] base64String2ByteFun(String base64Str){
//        return Base64.decodeFast(base64Str);
//    }
//
//
//
////    public   void  checkpic(HashMap<Integer, PackInfo> map){
////        try {
////            StringBuffer a = new StringBuffer();
////            Iterator<HashMap.Entry<Integer, PackInfo>> it = map.entrySet().iterator();
////            while (it.hasNext()) {
////                HashMap.Entry<Integer, PackInfo> entry = it.next();
////                PackInfo packinfo = entry.getValue();
////                a.append(packinfo.getData());
//////                System.out.println("长度base64" + a.toString());
////            }
////            System.out.println("长度base64" + a.toString());
////        }catch (Exception E){
////            E.printStackTrace();
////        }
////    }
//
//
//    // 检测放入的小包是否等于包的总数，等于则合成一张图片
//    public void checkMap(Map<Long, HashMap<Integer, PackInfo>> map) throws Exception {
//        Iterator<Map.Entry<Long, HashMap<Integer,PackInfo>>> it = map.entrySet().iterator();
//        while(it.hasNext()) {
//            Map.Entry<Long, HashMap<Integer,PackInfo>> entry = it.next();
//            PackInfo packinfo = entry.getValue().entrySet().iterator().next().getValue();
//            System.out.println("kk"+packinfo.toString());
//
//             //* 检测是否集齐了所有小包，集齐了就合成一帧图片
////            if(packinfo.getCount() == entry.getValue().size()) {
////                System.out.println("满了，合成图片");
//                // * 将各个小包合成图片
//                ByteArrayOutputStream baos = new ByteArrayOutputStream();
////                for(int i=0; i<packinfo.getCount(); i++){
////                    PackInfo p = entry.getValue().get(i);
////                    System.out.println("未解压缩的数据长度 = " + p.toString());
//////                    baos.write(p.getData());
////                }
//                baos.close();
//
//                 // 解压缩数据
//               // byte[] b = unCompressImage(baos.toByteArray());
//
//                System.out.println("未解压缩的数据长度 = " + baos.toByteArray().length);
//
//
//                 // 设置图片到面板中
//                BASE64Decoder d = new BASE64Decoder();
//                String imgBase64 = "data:image/png;base64,"+packinfo.getData();
//
//
//                System.out.println(imgBase64);
//                byte[] data = base64String2ByteFun(imgBase64);
//                System.out.println("13213213 =-============"+data.length);
//                FileOutputStream os = new FileOutputStream("E:\\wx\\d.jpg");
//                os.write(data);
//                os.close();
//                BufferedImage image = ImageIO.read(new ByteArrayInputStream(data));
//                ImageIcon i = new ImageIcon(image);
//                label.setIcon(i);
//                repaint();
//                System.out.println("设置一张图片");
//                //将设置过后的image数据从map中移除
//                it.remove();
//            }
//        }
////        System.out.println("字典长度 = " + map.size());
//    }
//
//
//
//    // 对合成的数据进行解压缩，返回解压的byte[]
////    private byte[] unCompressImage(byte[] b) throws IOException {
////        ByteArrayInputStream bais = new ByteArrayInputStream(b);
////        ZipInputStream zis = new ZipInputStream(bais);
////        zis.getNextEntry();
////        byte[] data = zis.readAllBytes();//
////        zis.close();
////        bais.close();
////        return data;
////    }
//
//
//// 存放包的数据的实例类
//class PackInfo {
//    private long time;  //  包的时间戳
//    private int count;  // 分割的包数量
//    private int num;    //  当前的包编号
//    private String data;  // 包中存放的数据
//
//    public long getTime() {
//        return time;
//    }
//    public void setTime(long time) {
//        this.time = time;
//    }
//    public int getCount() {
//        return count;
//    }
//    public void setCount(int count) {
//        this.count = count;
//    }
//    public int getNum() {
//        return num;
//    }
//    public void setNum(int num) {
//        this.num = num;
//    }
//    public String getData() {
//        return data;
//    }
//    public void setData(String data) {
//        this.data = data;
//    }
//
//    @Override
//    public String toString() {
//        return "PackInfo{" +
//                "time=" + time +
//                ", count=" + count +
//                ", num=" + num +
//                ", data='" + data + '\'' +
//                '}';
//    }
//}
//class TestEntity  {
//    private double TimeStamp;  //  包的时间戳
//    private int Index;  // 分割的包数量
//    private int Total;    //  当前的包编号
//    private String Data;  // 包中存放的数据
//    private  int TotalLength;
//    private  int DataOffset;
//    private  int DataLength;
//    public double getTimeStamp() {
//        return TimeStamp;
//    }
//
//    public void setTimeStamp(double timeStamp) {
//        TimeStamp = timeStamp;
//    }
//
//    public int getIndex() {
//        return Index;
//    }
//
//    public void setIndex(int index) {
//        Index = index;
//    }
//
//    public int getTotal() {
//        return Total;
//    }
//
//    public void setTotal(int total) {
//        Total = total;
//    }
//
//    public String getData() {
//        return Data;
//    }
//
//    public void setData(String Data) {
//        Data = Data;
//    }
//
//    @Override
//    public String toString() {
//        return "TestEntity{" +
//                "TimeStamp=" + TimeStamp +
//                ", Index=" + Index +
//                ", Total=" + Total +
//                ", Data='" + Data + '\'' +
//                ", TotalLength=" + TotalLength +
//                ", DataOffset=" + DataOffset +
//                ", DataLength=" + DataLength +
//                '}';
//    }
//
//    public int getTotalLength() {
//        return TotalLength;
//    }
//
//    public void setTotalLength(int totalLength) {
//        TotalLength = totalLength;
//    }
//
//    public int getDataOffset() {
//        return DataOffset;
//    }
//
//    public void setDataOffset(int dataOffset) {
//        DataOffset = dataOffset;
//    }
//
//    public int getDataLength() {
//        return DataLength;
//    }
//
//    public void setDataLength(int dataLength) {
//        DataLength = dataLength;
//    }
//}
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.zip.ZipInputStream;

public class  Main   extends JFrame {

    private static final long serialVersionUID = -580341982722536152L;
    // label用于放置image
    private JLabel label;

    public static void main(String[] args) {

        Main bsClient = new Main();
    }

    public Main() {
        init();
        Long startTimeMillis1 = System.currentTimeMillis();
        getData();
        Long endTimeMillis1 = System.currentTimeMillis() - startTimeMillis1;
        System.out.println("(发送) 结束，用时:"+ endTimeMillis1+" ms");
    }

    // 初始化面板设置，设置一个label，放置image
    public void init() {
       // this.setTitle("屏幕广播");
        this.setBounds(270, 80, 1100, 600);
        try {
//            BufferedImage image = ImageIO.read(new File("E://Test//demo.jpg"));//首页 可以放LOGO
//            ImageIcon icon = new ImageIcon(image);
            label = new JLabel();
            label.setBounds(25, 25, 1100, 600);
        } catch(Exception e) {
            e.printStackTrace();
        }
        this.add(label);

        // 监听窗口关闭事件，关闭窗口的同时停止程序
        this.addWindowListener(new WindowAdapter(){
            @Override
            public void windowClosing(WindowEvent e) {
               // System.out.println("关闭窗口");
                System.exit(-1);
            }
        });

        // 设置面板可见
        this.setVisible(true);
    }

    // 启动一个线程监听端口，接收数据，解析成image并放入面板中显示
    public void getData() {
        Thread t = new Thread() {
            private DatagramSocket receiver;
            MulticastSocket multicastSocket = null;
            @Override
            public void run() {
                try {
//                    InetAddress IP = InetAddress.getByName("192.168.0.172");
//                    receiver = new DatagramSocket(9999);
                    InetAddress group = InetAddress.getByName("224.5.6.7");
                    multicastSocket = new MulticastSocket(12345);
                    multicastSocket.joinGroup(group);
                    byte[] buffer = new byte[64*1024];
                    DatagramPacket pack = new DatagramPacket(buffer, buffer.length);
                   // System.out.println("等待接收数据");
                    // 用Map来存放image的各个包数据，Long是接收到数据包的时间戳，Integer是包的编号，
                    // PackInfo中存放了解析出来的包数据、包数量、包编号、时间戳
                    Map<Long, HashMap<Integer, PackInfo>> map = null;
                    // key用于存放接收的上一个包数据的时间戳
                    long key = 0;
                    while(true) {
                        multicastSocket.receive(pack);
                     //   System.out.println("收到一个数据报包 " + pack.getLength());
                        // 将收到的数据包解析成数据对象
                        PackInfo packinfo = parsePackInfo(pack);
                        // 如果接收的的数据时间戳大于之前的包的时间戳，则丢弃之前的map，新建一个map，放入新的数据
                        if(packinfo.getTime() > key) {
                            map = new HashMap<Long, HashMap<Integer,PackInfo>>();
                            HashMap<Integer,PackInfo> value = new HashMap<Integer,PackInfo>();
                            value.put(packinfo.getNum(), packinfo);
                            map.put(packinfo.getTime(), value);
                            // 更新key的值
                            key = packinfo.getTime();
                        }else if(packinfo.getTime() == key) {  //
                            map.get(key).put(packinfo.getNum(), packinfo);
                            // 检测是否够合成一张图片了，条件是map.value.size等于包的数量
                            checkMap(map);
                        }
                    }
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
        };
        // 作为守护线程，并启动
        t.setDaemon(true);
        t.start();
    }

    // 解析一个包的数据，并放入对象中返回
    private PackInfo parsePackInfo(DatagramPacket pack) {
        // 新建一个包数据对象存放数据
        PackInfo packinfo = new PackInfo();

        byte[] buffer = pack.getData();

        // 取出时间戳，0-7的字节
        long time = Utils.byte2Long(buffer, 0);
        packinfo.setTime(time);

        // 取出分割数量，8-11的字节
        int count = Utils.byte2Int(buffer, 8);
        packinfo.setCount(count);

        // 取出当前编号，12-15的字节
        int num = Utils.byte2Int(buffer, 12);
        packinfo.setNum(num);

        // 当前被压缩后的数据
        byte[] data = new byte[pack.getLength()-16];
        System.arraycopy(buffer, 16, data, 0, data.length);
        packinfo.setData(data);
        return packinfo;
    }

    // 检测放入的小包是否等于包的总数，等于则合成一张图片
    public void checkMap(Map<Long, HashMap<Integer, PackInfo>> map) throws Exception {
        Iterator<Map.Entry<Long, HashMap<Integer,PackInfo>>> it = map.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry<Long, HashMap<Integer,PackInfo>> entry = it.next();
            PackInfo packinfo = entry.getValue().entrySet().iterator().next().getValue();
            // 检测是否集齐了所有小包，集齐了就合成一帧图片
            if(packinfo.getCount() == entry.getValue().size()) {
               // System.out.println("满了，合成图片");
                // 将各个小包合成图片
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                for(int i=0; i<packinfo.getCount(); i++){
                    PackInfo p = entry.getValue().get(i);
                    baos.write(p.getData());
                }
                baos.close();
                // 解压缩数据
                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
               ZipInputStream zis = new ZipInputStream(bais);


               zis.getNextEntry();

                BufferedImage image = ImageIO.read(zis);
                ImageIcon i = new ImageIcon(image);
                label.setIcon(i);
                repaint();
                //System.out.println("设置一张图片");
                // 将设置过后的image数据从map中移除
                it.remove();
            }
        }
      //  System.out.println("字典长度 = " + map.size());
    }



    // 对合成的数据进行解压缩，返回解压的byte[]
//    private byte[] unCompressImage(byte[] b) throws IOException {
//        ByteArrayInputStream bais = new ByteArrayInputStream(b);
//        ZipInputStream zis = new ZipInputStream(bais);
//        zis.getNextEntry();
//        byte[] data = zis.readAllBytes();//
//        zis.close();
//        bais.close();
//        return data;
//    }
}

// 存放包的数据的实例类
class PackInfo {
    private long time;  //  包的时间戳
    private int count;  // 分割的包数量
    private int num;    //  当前的包编号
    private byte[] data;  // 包中存放的数据

    public long getTime() {
        return time;
    }
    public void setTime(long time) {
        this.time = time;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public byte[] getData() {
        return data;
    }
    public void setData(byte[] data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "PackInfo{" +
                "time=" + time +
                ", count=" + count +
                ", num=" + num +
                '}';
    }
}
